﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Kokomo.Speech;

namespace Kokomo.Environment
{
	/// <summary>
	/// Represents a workspace in the UI.
	/// </summary>
	/// <remarks>
	/// A region is a work area that exposes commands for
	/// the user to complete a task.
	/// This class implements <see cref="ISpeechScope"/> to make the commands
	/// accessible via speech input.
	/// </remarks>
	public class RegionViewModel : NotifierObject, ISpeechScope
	{
		/// <summary>
		/// Initializes a new instance of <see cref="RegionViewModel"/>.
		/// </summary>
		protected RegionViewModel()
		{
			this._commands = new Dictionary<string, ICommand>();
		}

		private Dictionary<string, ICommand> _commands;

		/// <summary>
		/// Registers a command.
		/// </summary>
		/// <param name="command">The command.</param>
		/// <param name="name">The name of the command.</param>
		/// <exception cref="ArgumentNullException"><paramref name="command"/> is <c>null</c>.</exception>
		/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c>.</exception>
		/// <remarks>
		/// Other than uniquely identifying a command, <paramref name="name"/> has
		/// no semantic significance.
		/// </remarks>
		protected void RegisterCommand(ICommand command, string name)
		{
			if (command == null) throw new ArgumentNullException("command");
			if (name == null) throw new ArgumentNullException("name");

			// TODO: Check for duplicate entry
			this._commands[name] = command;
		}
		/// <summary>
		/// Gets a command by name.
		/// </summary>
		/// <param name="name">The name of the command.</param>
		/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c>.</exception>
		/// <returns>The <see cref="ICommand"/> identified by <paramref name="name"/>, if found;
		/// otherwise, <c>null</c>.</returns>
		protected ICommand GetCommand(string name)
		{
			if (name == null) throw new ArgumentNullException("name");

			ICommand command;
			this._commands.TryGetValue(name, out command);

			return command;
		}

		bool ISpeechScope.HandleCommand(string commandName, object argument)
		{
			if (commandName == null) return false;

			ICommand command = this.GetCommand(commandName);
			if (command == null) return false;
			if (!command.CanExecute(null)) return false;

			command.Execute(argument);

			return true;
		}
	}
}
